package com.example.soss.advice;

import com.alibaba.fastjson.JSON;
import com.example.soss.entity.Result;
import com.example.soss.entity.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;


/**
 * 全局异常处理，validation参数校验处理
 */
@ControllerAdvice(annotations = Controller.class)
@Slf4j
public class ExceptionAdvice {

    @ExceptionHandler(Exception.class)
    public void handlerException(HttpServletRequest request, HttpServletResponse response, Exception e) throws IOException {

        log.error("服务器发生异常：{}-{}", e.getMessage(), e.getClass().getName());
        for (StackTraceElement stackTraceElement : e.getStackTrace()) {
            log.error("{}", stackTraceElement);
        }

        String xRequestedWith = request.getHeader("x-requested-with");
        if ("XMLHttpRequest".equals(xRequestedWith)) {
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            PrintWriter writer = response.getWriter();
            writer.write(JSON.toJSONString(Result.failure(ResultEnum.ERROR)));
            writer.close();
        } else {
            response.sendRedirect(request.getContextPath() + "/500");
        }
    }


    //处理validation参数校验的注解
    @ResponseBody
    @ExceptionHandler(BindException.class)
    public Result paramCheck(BindException ex) {
        String defaultMessage = ex.getBindingResult().getFieldError().getDefaultMessage();
        return Result.failure(defaultMessage);
    }

    //单一参数校验
    @ResponseBody
    @ExceptionHandler(ConstraintViolationException.class)
    public Result paramCheck(ConstraintViolationException ex) {
        Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
        String message = constraintViolations.iterator().next().getMessage();
        return Result.failure(message);
    }
}
